import Taro, { RecorderManager } from '@tarojs/taro';
import TIMUploadPlugin from 'tim-upload-plugin'; // 使用前请将 IM SDK 升级到v2.9.2或更高版本
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import { arrayAdd, arrayRemove, arrayUpdate } from '@datorama/akita';
import TIM from 'tim-wx-sdk';

import config from '@/config';
import { CMD, MSG } from '@/constants/message';
import { MessageQuery, MessageStore } from "@/state/message/store";
import { AuthQuery } from '@/state/auth/store';
import { MessageItem } from '@/models/Message';
import { CustomMessage } from '@/models/request/msgReq';

import { isJSON } from '.';

//tim单例工厂
export class TimHandler {
  private static _instance: TimHandler;

  //单例方法
  public static getInstance(store: MessageStore, query: MessageQuery, authQuery: AuthQuery): TimHandler {
    if (this._instance == null) {
      this._instance = new TimHandler(store, query, authQuery);
    }
    return this._instance;
  }

  constructor(private store: MessageStore, private query: MessageQuery, private authQuery: AuthQuery) {
    //没有箭头的函数定义需要bind
    this.onReadyStateUpdate = this.onReadyStateUpdate.bind(this);
    this.updateMyProfile = this.updateMyProfile.bind(this);
    this.kickOut = this.kickOut.bind(this);
    this.onErr = this.onErr.bind(this);
    this.checkoutNetState = this.checkoutNetState.bind(this);
    this.netStateChange = this.netStateChange.bind(this);
    this.messageReceived = this.messageReceived.bind(this);
    this.convListUpdate = this.convListUpdate.bind(this);
    this.groupListUpdate = this.groupListUpdate.bind(this);
    this.blackListUpdate = this.blackListUpdate.bind(this);
    this.messageRevoked = this.messageRevoked.bind(this);
  }

  private tim = TIM.create({
    SDKAppID: config.IM_CONF.SDKAPPID
  })
  // 1. 获取全局唯一的录音管理器 RecorderManager
  private recorderManager = Taro.getRecorderManager();

  private mTimeDiff = 0;   //本机与服务器时间差
  private isSDKReady = false; //默认未登录状态
  private nextReqMsgId = '';  //用于拉取下一页IM消息的标识字段
  private isCompleted = false; //是否已分页拉取拉完消息
  //notifyMsg = new Subject<Record<string, any>>(); //用于发送一次性通知

  //初始化方法
  initTimSDK = (userID: string, userSig: string) => {
    const promise = this.tim.login({ userID, userSig })
      .then((imResponse: any) => {
        if (imResponse.data.repeatLogin === true) {
          // 标识账号已登录，本次登录操作为重复登录。v2.5.1 起支持
          console.log("之前已登录过", imResponse.data.errorInfo);
        } else {
          console.log("IM登录完成", imResponse.data.errorInfo);
        }
      })
      .catch((err: any) => {
        console.error("登录出错: ", err);
      })

    return promise as Promise<any>;
  }

  bindOn = () => {
    // 设置 SDK 日志输出级别，详细分级请参见 setLogLevel 接口的说明
    if (config.ENV === "production") {
      // release级别，SDK 输出关键信息，生产环境时建议使用
      this.tim.setLogLevel(1);
    } else {
      //普通级别，日志量较多，接入时建议使用
      this.tim.setLogLevel(0);
    }
    dayjs.locale('zh-cn');

    // 注册腾讯云即时通信 IM 上传插件，即时通信 IM SDK 发送图片、语音、视频、文件等消息需要使用上传插件，将文件上传到腾讯云对象存储
    this.tim.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin });

    this.tim.on(TIM.EVENT.SDK_READY, this.onReadyStateUpdate, this);
    this.tim.on(TIM.EVENT.SDK_NOT_READY, this.onReadyStateUpdate, this);
    this.tim.on(TIM.EVENT.KICKED_OUT, this.kickOut, this);
    // 出错统一处理
    this.tim.on(TIM.EVENT.ERROR, this.onErr, this);

    this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.messageReceived, this);
    this.tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.convListUpdate, this);
    this.tim.on(TIM.EVENT.GROUP_LIST_UPDATED, this.groupListUpdate, this);
    this.tim.on(TIM.EVENT.BLACKLIST_UPDATED, this.blackListUpdate, this);
    this.tim.on(TIM.EVENT.NET_STATE_CHANGE, this.netStateChange, this);
    this.tim.on(TIM.EVENT.MESSAGE_REVOKED, this.messageRevoked, this);
  }

  bindOff = () => {
    this.tim.off(TIM.EVENT.SDK_READY, this.onReadyStateUpdate);
    this.tim.off(TIM.EVENT.SDK_NOT_READY, this.onReadyStateUpdate);

    this.tim.off(TIM.EVENT.KICKED_OUT, this.kickOut);
    // 出错统一处理
    this.tim.off(TIM.EVENT.ERROR, this.onErr);

    this.tim.off(TIM.EVENT.MESSAGE_RECEIVED, this.messageReceived);
    this.tim.off(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.convListUpdate);
    this.tim.off(TIM.EVENT.GROUP_LIST_UPDATED, this.groupListUpdate);
    this.tim.off(TIM.EVENT.BLACKLIST_UPDATED, this.blackListUpdate);
    this.tim.off(TIM.EVENT.NET_STATE_CHANGE, this.netStateChange);
  }

  onReadyStateUpdate({ name }) {
    // 注意：login 成功才会驱动 SDK 触发 SDK_READY 事件
    this.isSDKReady = (name === TIM.EVENT.SDK_READY);
    this.store.update(state => {
      state.isSDKReady = this.isSDKReady;
    })
    if (this.authQuery.userInfo.nickName) {
      this.updateMyProfile(this.authQuery.userInfo.nickName, this.authQuery.userInfo.avatarUrl || "");
    }
  }

  updateMyProfile = (nickName: string, avatarUrl: string) => {
    if (this.isSDKReady) {
      this.tim.updateMyProfile({
        nick: nickName,
        avatar: avatarUrl
      })
        .then((res: any) => {
          console.log("更新个人头像和昵称成功: ", res.data);
        })
        .catch((err: any) => {
          console.error("更新个人头像和昵称失败: ", err);
        })

      this.tim.getMyProfile().then((res: { data: any; }) => {
        console.log("更新个人信息: ", res.data)
      })
      this.tim.getBlacklist().then((res: { data: any; }) => {
        console.log("设置黑名单: ", res.data)
      })
    }
  }

  kickOut(event: any) {
    console.log("被踢下线: ", event)
  }

  onErr(event: any) {
    // 网络错误不弹toast && sdk未初始化完全报错
    if (event.data.message && event.data.code && event.data.code !== 2800 && event.data.code !== 2999) {
      console.log("TIM出现错误: ", event.data.message)
    }
  }

  checkoutNetState(state: string) {
    switch (state) {
      case TIM.TYPES.NET_STATE_CONNECTED:
        console.warn("已接入网络");
        break;
      case TIM.TYPES.NET_STATE_CONNECTING:
        console.warn("当前网络不稳定");
        break;
      case TIM.TYPES.NET_STATE_DISCONNECTED:
        console.warn("当前网络不可用");
        break;
      default:
        break;
    }
  }

  netStateChange(event: any) {
    this.checkoutNetState(event.data.state);
  }

  messageReceived(event: any) {
    for (let i = 0; i < event.data.length; i++) {
      const item = event.data[i];

      //不处理重复消息
      //if (this.lastMsg && this.lastMsg.random && this.lastMsg.random === item.random) continue;
      switch (item.type) {
        case TIM.TYPES.MSG_GRP_TIP: //群提示消息
          {
            //参考文档  https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/Message.html#.GroupTipPayload
            if (item.payload.operationType === 1) {
              console.log("有新成员加入: ", item);
              let text = item.nick;
              //如果有多人同时进入房间
              if (item.payload.userIDList.length > 1) {
                text += "等" + item.payload.userIDList.length + "人";
              }
              text += "进入房间";

              this.store.update(state => {
                state.enterMsg = text;
              })
            }
            break;
          }
        case TIM.TYPES.MSG_CUSTOM: //自定义消息， 包括了图文直播发送的文本、图片和语音消息
        case TIM.TYPES.MSG_AUDIO:
        case TIM.TYPES.MSG_IMAGE:
          {
            //目前仅仅只用于连麦发送和踢人，只有C2C类型消息
            console.log("收到自定义消息消息", item);

            if (isJSON(item.payload.data)) {
              //直接返回消息体字符串，由直播间的方法进行反序列化，不在这里处理
              const content = JSON.parse(item.payload.data);

              //图文直播的文本处理
              if (content.cmd == CMD.TUWEN_TEXT) {
                this.dealTuwenMsgList(item)
              } else {
                // console.warn("timHandler C2C通知消息收到时间：", new Date().getTime());

                //TODO 其他特殊指令处理
                this.store.update(state => {
                  state.notifyMsg = content;
                })

                //this.notifyMsg.next(content);
              }
            } else {
              //图文和音频消息入库
              this.dealTuwenMsgList(item);
            }
            break;
          }
        case TIM.TYPES.MSG_TEXT: {//普通文本消息，考虑作用域提升问题，需要使用花括号{}包住
          console.log("收到文本消息", item);
          this.dealMsgList(item);
          break;
        }
        case TIM.TYPES.MSG_GRP_SYS_NOTICE: //群系统通知消息
          {
            // console.warn("收到群通知消息", item);
            // console.warn("timHandler群发通知消息收到时间：", new Date().getTime());
            if (isJSON(item.payload.userDefinedField)) {
              //解析系统消息的数据体，获取自定义数据，消息结构参考官方文档
              const notifyMsg: Record<string, any> = JSON.parse(item.payload.userDefinedField);

              this.store.update(state => {
                state.notifyMsg = notifyMsg;
              })

              // this.notifyMsg.next(notifyMsg);
            }
            break;
          }
        default:
          console.log("其他消息类型", item);
          break;
      }
    }
  }

  convListUpdate(event: any) {
    //console.log("会话列表更新", event.data);
  }

  groupListUpdate(event: any) {
    console.log("群组列表更新", event.data);
  }

  blackListUpdate(event: any) {
    console.log("黑名单列表更新", event.data);
  }

  messageRevoked(event: any) {
    for (let i = 0; i < event.data.length; i++) {
      const item = event.data[i] as MessageItem;

      //消息撤回标记
      if (item.isRevoked) {
        this.store.update(({ msgList }) => ({
          msgList: arrayUpdate(msgList, item.random, item, "random")
        }))
      }
    }
  }

  /**
   * FIXME  这里容易踩坑，腾讯云需要的是groupID而不是groupId
   * @param {*} groupID 群ID，也是房间roomID
   */
  applyJoinBigGroup = (groupID: string) => {
    const promise = new Promise<any>((resole, reject) => {
      this.tim.joinGroup({ groupID, type: TIM.TYPES.GRP_AVCHATROOM })
        .then((imResponse: any) => {
          switch (imResponse.data.status) {
            case TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL: // 等待管理员同意, 暂不处理
              break;
            case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
              console.log("加群成功: ", imResponse.data.group); // 加入的群组资料
              break;
            case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
              console.log("已在群内")
              break;
            default:
              break;
          }
          this.store.update(state => {
            state.groupId = groupID;
          })
          resole(true);
        }).catch((imError: any) => {
          console.error('joinGroup error:', imError); // 申请加群失败的相关信息
          reject(false);
        })
    })
    return promise;
  }

  //注销IM和websocket
  logOut = () => {
    this.tim.logout();
    //重置消息拉取状态
    this.resetGroup();
  }

  /**
   * 退出大群
   */
  quitBigGroup = (groupID: string) => {
    this.tim.quitGroup(groupID)
      .then((imResponse: any) => {
        console.log(imResponse.data.groupID); // 退出成功的群 ID
      }).catch((imError: any) => {
        console.warn('quitGroup error:', imError); // 退出群组失败的相关信息
      });

    this.resetGroup();
  }

  /**
   * 获取当前房间消息，没有则拉取最近15条消息
   */
  getRoomMsgs = async (groupID: string) => {
    //已有消息则直接返回
    //if (this.query.msgList.length > 0) return this.query.msgList;

    // BUG打开某个会话时，第一次拉取消息列表
    const imResponse = await this.tim.getMessageList({ conversationID: 'GROUP' + groupID })
      .catch((imError: any) => {
        console.error('群消息拉取错误:', imError);
      })

    this.nextReqMsgId = imResponse.data.nextReqMessageID;
    this.isCompleted = imResponse.data.isCompleted;

    this.store.update(({ msgList }) => ({
      msgList: arrayAdd(msgList, imResponse.data.messageList)
    }));

    return this.query.msgList;
  }

  /**
   * 翻页拉取10条消息
   */
  getPagingMsgs = async (groupID: string) => {
    // 打开某个会话时，第一次拉取消息列表
    const nextReqMessageID = this.nextReqMsgId;

    if (!nextReqMessageID) {
      return await this.getRoomMsgs(groupID);
    } else {
      const imResponse = await this.tim.getMessageList({
        conversationID: 'GROUP' + groupID,
        nextReqMessageID,
        count: MSG.GROUP_MESSAGE_LENGTH
      })
        .catch((imError: any) => {
          console.error('群消息分页拉取错误:', imError);
        })

      const newMessages = imResponse.data.messageList as MessageItem[]; // 消息列表。
      // 本地只保存最大100条消息
      if (this.query.msgList.length > MSG.MAX_GROUP_MESSAGE_LENGTH) {
        this.store.update(({ msgList }) => ({
          //超出100条，则删除最早的N条消息
          msgList: arrayRemove(msgList, (item, index) => { return index ? index < newMessages.length : false })
        }))
      }

      this.nextReqMsgId = imResponse.data.nextReqMessageID;
      this.isCompleted = imResponse.data.isCompleted;

      this.store.update(({ msgList }) => ({
        msgList: arrayAdd(msgList, newMessages)
      }));

      return this.query.msgList;
    }
  }

  /**
  * 发送群组消息
  * @param {*} options
  */
  sendRoomTextMsg = (groupId: string, msg: string) => {
    console.log("输入文本内容: ", msg)
    // 1. 创建消息实例，接口返回的实例可以上屏
    const message = this.tim.createTextMessage({
      to: groupId, //消息接收方的 userId 或 groupID
      conversationType: TIM.TYPES.CONV_GROUP,
      // 消息优先级，用于群聊（v2.4.2起支持）。如果某个群的消息超过了频率限制，后台会优先下发高优先级的消息，详细请参考：https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
      // 支持的枚举值：TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL（默认）, TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
      // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
      payload: {
        text: msg
      }
    })
    console.log("要发送的消息：", message)
    this.dealMsgList(message);

    // 2. 发送消息
    return this.tim.sendMessage(message) as Promise<any>;
  }

  //群发图片消息
  sendRoomImageMsg = (groupId: string) => {
    const newPromise = new Promise((resolve, reject) => {
      Taro.chooseImage({
        count: 1,  // 只选一张，目前 SDK 不支持一次发送多张图片
        sizeType: ['original'], // 可以指定是原图还是压缩图，默认二者都有
        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机，默认二者都有，在H5浏览器端支持使用 `user` 和 `environment`分别指定为前后摄像头 
        success: (res) => {
          // 2. 创建消息实例，接口返回的实例可以上屏
          const message = this.tim.createImageMessage({
            to: groupId,
            conversationType: TIM.TYPES.CONV_GROUP,
            priority: TIM.TYPES.MSG_PRIORITY_HIGH,
            payload: { file: res },
            onProgress: function (event: any) { console.log('file uploading:', event) }
          });

          this.dealTuwenMsgList(message);

          // 3. 发送图片
          const promise = this.tim.sendMessage(message) as Promise<any>;
          promise.then(function (imResponse) {
            // 发送成功
            console.log(imResponse);
            resolve(imResponse);
          }).catch(function (imError) {
            // 发送失败
            console.error('sendMessage error:', imError);
            reject(imError);
          });
        }
      })
    }).then(res => {
      console.log('图片数据：', res);
    }).catch(err => console.log(err, '错误')
    )

    return newPromise;
  }

  //开始录制音频消息
  startRoomAudioMsg = (groupId: string, cancelRecord: boolean) => {
    const newPromise = new Promise((resolve, reject) => {
      // 示例：使用微信官方的 RecorderManager 进行录音，参考 https://developers.weixin.qq.com/minigame/dev/api/media/recorder/RecorderManager.start.html
      // 1. 获取全局唯一的录音管理器 RecorderManager
      //const recorderManager = Taro.getRecorderManager();

      // 录音部分参数
      const recordOptions = {
        duration: 60000, // 录音的时长，单位 ms，最大值 600000（10 分钟）
        sampleRate: 44100, // 采样率
        numberOfChannels: 1, // 录音通道数
        encodeBitRate: 192000, // 编码码率
        format: "aac" // 音频格式，选择此格式创建的音频消息，可以在即时通信 IM 全平台（Android、iOS、微信小程序和Web）互通
      };

      // 2.1 监听录音错误事件
      this.recorderManager.onError(errMsg => {
        console.warn('recorder error:', errMsg);
        reject(errMsg);
      });
      // 2.2 监听录音结束事件，录音结束后，调用 createAudioMessage 创建音频消息实例
      this.recorderManager.onStop(res => {
        console.log('recorder stop', res);
        console.log(' 是否取消录音：', cancelRecord);
        if (cancelRecord) {
          console.log('取消发送消息')
        } else {
          // 4. 创建消息实例，接口返回的实例可以上屏
          const message = this.tim.createAudioMessage({
            to: groupId,
            conversationType: TIM.TYPES.CONV_GROUP,
            // 消息优先级，用于群聊（v2.4.2起支持）。如果某个群的消息超过了频率限制，后台会优先下发高优先级的消息，详细请参考：https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
            // 支持的枚举值：TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL（默认）, TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
            // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
            payload: {
              file: res
            },
            onProgress: (event) => {
              console.log('上传录音的回调进度', event)
            }
          });

          this.dealTuwenMsgList(message);
          // 5. 发送消息
          const promise = this.tim.sendMessage(message) as Promise<any>;

          promise.then(function (imResponse) {
            // 发送成功
            console.log(imResponse);
            resolve(imResponse);
          }).catch(function (imError) {
            // 发送失败
            console.warn('sendMessage error:', imError);
            reject(imError);
          });
        }

      });

      // 3. 开始录音
      this.recorderManager.start(recordOptions as RecorderManager.StartOption);
    })

    return newPromise;
  }

  //结束录制音频消息
  sendRoomAudioMsg = () => {
    this.recorderManager.stop();
  }

  //发送视频消息
  sendRoomVideoMsg = (groupId: string) => {
    const newPromise = new Promise((resolve, reject) => {
      // 小程序端发送视频消息示例：
      // 1. 调用小程序接口选择视频，接口详情请查阅 https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseVideo.html
      Taro.chooseVideo({
        sourceType: ['album', 'camera'], // 来源相册或者拍摄
        maxDuration: 60, // 设置最长时间60s
        camera: 'back', // 后置摄像头
        success(res) {
          // 2. 创建消息实例，接口返回的实例可以上屏
          const message = this.tim.createVideoMessage({
            to: groupId,
            conversationType: TIM.TYPES.CONV_GROUP,
            // 消息优先级，用于群聊（v2.4.2起支持）。如果某个群的消息超过了频率限制，后台会优先下发高优先级的消息，详细请参考：https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
            // 支持的枚举值：TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL（默认）, TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
            priority: TIM.TYPES.MSG_PRIORITY_HIGH,
            payload: {
              file: res
            }
          })
          // 3. 发送消息
          const promise = this.tim.sendMessage(message) as Promise<any>;

          promise.then(function (imResponse) {
            // 发送成功
            resolve(imResponse);
          }).catch(function (imError) {
            // 发送失败
            reject(imError);
          });
        }
      })
    })

    return newPromise;
  }

  /**
  * 发送群自定义消息
  * @param {*} options 
  */
  sendRoomCustomMsg = (roomId: string, msg: CustomMessage) => {
    // 2. 创建消息实例，接口返回的实例可以上屏
    const message = this.tim.createCustomMessage({
      to: roomId, //消息接收方的 userID 或 groupID
      conversationType: TIM.TYPES.CONV_GROUP,
      priority: TIM.TYPES.MSG_PRIORITY_HIGH,
      payload: {
        data: msg.data, // 内容
        description: msg.description, // 标识
        extension: msg.extension
      }
    });

    console.log("要发送的自定义消息：", message)
    this.dealTuwenMsgList(message);

    // 3. 发送消息
    return this.tim.sendMessage(message) as Promise<any>;
  }

  /**
   * 发送C2C自定义消息
   * @param {*} options 
   */
  sendC2cCustomMsg = (userId: string, msg: CustomMessage) => {
    // 2. 创建消息实例，接口返回的实例可以上屏
    const message = this.tim.createCustomMessage({
      to: userId, //消息接收方的 userID 或 groupID
      conversationType: TIM.TYPES.CONV_C2C,
      priority: TIM.TYPES.MSG_PRIORITY_HIGH,
      payload: {
        data: msg.data, // 内容
        description: msg.description, // 标识
        extension: msg.extension
      }
    });

    // 3. 发送消息
    return this.tim.sendMessage(message) as Promise<any>;
  }

  /**
   * 对某个用户禁言或取消禁言
   * @param options
   */
  muteGroupMember = (groupId: string, userId: string, muteTime?: number) => {
    this.tim.setGroupMemberMuteTime({
      groupID: groupId,
      userID: userId,
      muteTime: muteTime || 0 // 禁言10分钟；设为0，则表示取消禁言
    })
      .then((imResponse: any) => {
        console.log(imResponse.data.group); // 修改后的群资料
        console.log(imResponse.data.member); // 修改后的群成员资料
        Promise.resolve();
      })
      .catch((imError: any) => {
        console.error('setGroupMemberMuteTime error:', imError); // 禁言失败的相关信息
        Promise.reject();
      })
  }

  /**
   * 设置群组成员角色
   * @param options
   */
  setGroupMemberRole = (groupId: string, userId: string, role?: string) => {
    this.tim.setGroupMemberRole({
      groupID: groupId,
      userID: userId,
      role: role || TIM.TYPES.GRP_MBR_ROLE_ADMIN //可选值：TIM.TYPES.GRP_MBR_ROLE_ADMIN（群管理员） 或 TIM.TYPES.GRP_MBR_ROLE_MEMBER（群普通成员）
    })
      .then((imResponse: any) => {
        console.log(imResponse.data.group); // 修改后的群资料
        console.log(imResponse.data.member); // 修改后的群成员资料
      })
      .catch((imError: any) => {
        console.error('setGroupMemberMuteTime error:', imError); // 禁言失败的相关信息
      })
  }

  /**
   * 撤回消息
   * @param options
   */
  revokeMessage = (msg: MessageItem) => {
    return this.tim.revokeMessage(msg) as Promise<any>;
  }

  dealMsgList = (item: MessageItem) => {
    const msgListRef = this.query.msgList;
    //数组最后一条消息
    const lastMsg = msgListRef[msgListRef.length - 1];

    //简化版消息去重
    if (lastMsg && lastMsg.random === item.random && (item.time - lastMsg.time <= 300)) return;

    if (msgListRef.length >= MSG.MAX_GROUP_MESSAGE_LENGTH) {
      //TODO 超出100条，则删除最早的1条
      this.store.update(({ msgList }) => ({
        msgList: arrayRemove(msgList, (i, idx) => idx === 0)
      }));
    }

    this.store.update(({ msgList }) => ({
      msgList: arrayAdd(msgList, item)
    }))
  }

  //图文直播聊天数据处理
  dealTuwenMsgList = (item: MessageItem) => {
    const tuwenListRef = this.query.tuwenMsgList;
    //数组最后一条消息
    const lastTuwenMsg = tuwenListRef[tuwenListRef.length - 1];
    console.log('图文消息内容：', item)

    //简化版消息去重
    if (lastTuwenMsg && lastTuwenMsg.random === item.random && (item.time - lastTuwenMsg.time <= 300)) return;

    // if (myMsgList.length >= MSG.MAX_GROUP_MESSAGE_LENGTH) {
    //   //TODO 超出100条，则删除最早的1条
    //   this.store.update(({ tuwenMsgList }) => ({
    //     tuwenMsgList: arrayRemove(tuwenMsgList, (i, idx) => idx === 0)
    //   }));
    // }

    this.store.update(({ tuwenMsgList }) => ({
      tuwenMsgList: arrayAdd(tuwenMsgList, item)
    }))
  }

  //重置聊天群组数据
  resetGroup = (newGroupId?: string) => {
    //不传newGroupId就强制清理数据
    if (newGroupId) {
      if (!this.query.groupId || this.query.groupId === newGroupId) {
        return;
      }
    }

    this.nextReqMsgId = '';
    this.isCompleted = false;

    //重置store
    this.store.update(state => {
      state.groupId = "";
      state.enterMsg = "";
      state.notifyMsg = {};
      state.msgList = [];
      state.tuwenMsgList = [];
    })
  }

  //参考https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/SDK.html#getGroupMemberProfile
  getMemberInfo = (groupId: string, userIds: string[], customFields?: string[]) => {
    return this.tim.getGroupMemberProfile({
      groupID: groupId,
      userIDList: userIds, // 请注意：即使只拉取一个群成员的资料，也需要用数组类型，例如：userIDList: ['user1']
      memberCustomFieldFilter: customFields, // 筛选群成员自定义字段：group_member_custom
    }) as Promise<any>
  }
}

export const makeHandler = (store: MessageStore, query: MessageQuery, authQuery: AuthQuery): TimHandler => {
  const handler = TimHandler.getInstance(store, query, authQuery);

  return handler;
}